package com.frank.oj.controller.admin;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.frank.model.entity.contest.Contest;
import com.frank.model.entity.contest.ContestProblem;
import com.frank.model.entity.problem.Problem;
import com.frank.oj.common.result.CommonResult;
import com.frank.oj.model.dto.AnnouncementDTO;
import com.frank.oj.model.dto.ContestProblemDTO;
import com.frank.oj.model.dto.ProblemDTO;
import com.frank.oj.model.vo.AdminContestVO;
import com.frank.oj.model.vo.AnnouncementVO;
import com.frank.oj.service.admin.contest.AdminContestAnnouncementService;
import com.frank.oj.service.admin.contest.AdminContestProblemService;
import com.frank.oj.service.admin.contest.AdminContestService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author frank
 * @Date 2024/4/7
 */
@RestController
@RequiresAuthentication
@RequestMapping("/api/admin/contest")
public class AdminContestController {

    @Resource
    private AdminContestService adminContestService;
    @Resource
    private AdminContestProblemService adminContestProblemService;
    @Resource
    private AdminContestAnnouncementService adminContestAnnouncementService;

    /**
     * 比赛列表
     *
     * @param limit       10
     * @param currentPage 1
     * @param keyword     *
     * @return page
     */
    @GetMapping("/get-contest-list")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<IPage<Contest>> getContestList(@RequestParam(value = "limit", required = false) Integer limit,
                                                       @RequestParam(value = "currentPage", required = false) Integer currentPage,
                                                       @RequestParam(value = "keyword", required = false) String keyword) {
        return adminContestService.getContestList(limit, currentPage, keyword);
    }

    /**
     * 修改比赛可见性
     *
     * @param cid     比赛id
     * @param uid     用户id
     * @param visible 可见性
     * @return null
     */
    @PutMapping("/change-contest-visible")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> changeContestVisible(@RequestParam(value = "cid", required = true) Long cid,
                                                   @RequestParam(value = "uid", required = true) String uid,
                                                   @RequestParam(value = "visible", required = true) Boolean visible) {

        return adminContestService.changeContestVisible(cid, uid, visible);
    }


    /**
     * 增
     *
     * @param adminContestVo 比赛信息
     * @return null
     */
    @PostMapping("")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> addContest(@RequestBody AdminContestVO adminContestVo) {

        return adminContestService.addContest(adminContestVo);
    }

    /**
     * 删
     *
     * @param cid 比赛id
     * @return null
     */
    @DeleteMapping("")
    @RequiresRoles(value = "root") // 只有超级管理员能删除比赛
    public CommonResult<Void> deleteContest(@RequestParam("cid") Long cid) {

        return adminContestService.deleteContest(cid);
    }

    /**
     * 改
     *
     * @param adminContestVo 比赛信息
     * @return null
     */
    @PutMapping("")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Void> updateContest(@RequestBody AdminContestVO adminContestVo) {

        return adminContestService.updateContest(adminContestVo);
    }

    /**
     * 查
     *
     * @param cid 比赛id
     * @return 比赛信息
     */
    @GetMapping("")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<AdminContestVO> getContest(@RequestParam("cid") Long cid) {

        return adminContestService.getContest(cid);
    }

    /**
     * 获取比赛题目列表
     *
     * @param limit       10
     * @param currentPage 1
     * @param keyword     *
     * @param cid         比赛id
     * @param problemType 题目类型
     * @param oj          类型
     * @return map
     */
    @GetMapping("/get-problem-list")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<HashMap<String, Object>> getProblemList(@RequestParam(value = "limit", required = false) Integer limit,
                                                                @RequestParam(value = "currentPage", required = false) Integer currentPage,
                                                                @RequestParam(value = "keyword", required = false) String keyword,
                                                                @RequestParam(value = "cid", required = true) Long cid,
                                                                @RequestParam(value = "problemType", required = false) Integer problemType,
                                                                @RequestParam(value = "oj", required = false) String oj) {

        return adminContestProblemService.getProblemList(limit, currentPage, keyword, cid, problemType, oj);
    }

    /**
     * 题目信息
     *
     * @param pid     题目id
     * @param request request
     * @return problem
     */
    @GetMapping("/problem")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Problem> getProblem(@RequestParam("pid") Long pid, HttpServletRequest request) {
        return adminContestProblemService.getProblem(pid);
    }

    /**
     * 获取比赛题目信息
     *
     * @param cid 比赛id
     * @param pid 题目id
     * @return 比赛题目
     */
    @GetMapping("/contest-problem")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<ContestProblem> getContestProblem(@RequestParam(value = "cid", required = true) Long cid,
                                                          @RequestParam(value = "pid", required = true) Long pid) {

        return adminContestProblemService.getContestProblem(cid, pid);
    }

    /**
     * 修改比赛题目
     *
     * @param contestProblem 比赛题目
     * @return 比赛题目
     */
    @PutMapping("/contest-problem")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<ContestProblem> setContestProblem(@RequestBody ContestProblem contestProblem) {

        return adminContestProblemService.setContestProblem(contestProblem);
    }

    /**
     * 比赛克隆
     *
     * @param cid 比赛id
     * @return null
     */
    @GetMapping("/clone")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> cloneContest(@RequestParam("cid") Long cid) {
        return adminContestService.cloneContest(cid);
    }

    /**
     * 删比塞题{有cid时仅将题目移出比赛，无cid时删除题目}
     *
     * @param pid 题目id
     * @param cid 比赛id
     * @return null
     */
    @DeleteMapping("/problem")
    @RequiresRoles(value = {"root", "problem_admin"}, logical = Logical.OR)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Void> deleteProblem(@RequestParam("pid") Long pid,
                                            @RequestParam(value = "cid", required = false) Long cid) {
        return adminContestProblemService.deleteProblem(pid, cid);
    }

    /**
     * 比赛页创建题目
     *
     * @param problemDto 题目信息
     * @return pid
     */
    @PostMapping("/problem")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Map<Object, Object>> addProblem(@RequestBody ProblemDTO problemDto) {

        return adminContestProblemService.addProblem(problemDto);
    }

    /**
     * 更新比赛题目
     *
     * @param problemDto 题目信息
     * @return null
     */
    @PutMapping("/problem")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Void> updateProblem(@RequestBody ProblemDTO problemDto) {

        return adminContestProblemService.updateProblem(problemDto);
    }

    /**
     * 从公共题目库添加题目
     *
     * @param contestProblemDto 比赛题目信息
     * @return null
     */
    @PostMapping("/add-problem-from-public")
    @RequiresAuthentication
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> addProblemFromPublic(@RequestBody ContestProblemDTO contestProblemDto) {

        return adminContestProblemService.addProblemFromPublic(contestProblemDto);
    }

    /**
     * 从公共题目库添加题目
     *
     * @param name      题目名称
     * @param problemId 题目id
     * @param cid       比赛id
     * @param displayId 题目展示id
     * @return null
     */
    @GetMapping("/import-remote-oj-problem")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Void> importContestRemoteOJProblem(@RequestParam("name") String name,
                                                           @RequestParam("problemId") String problemId,
                                                           @RequestParam("cid") Long cid,
                                                           @RequestParam("displayId") String displayId) {

        return adminContestProblemService.importContestRemoteOJProblem(name, problemId, cid, displayId);
    }

    @GetMapping("/announcement")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<IPage<AnnouncementVO>> getAnnouncementList(@RequestParam(value = "limit", required = false) Integer limit,
                                                                   @RequestParam(value = "currentPage", required = false) Integer currentPage,
                                                                   @RequestParam(value = "cid", required = true) Long cid) {

        return adminContestAnnouncementService.getAnnouncementList(limit, currentPage, cid);
    }

    @DeleteMapping("/announcement")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> deleteAnnouncement(@RequestParam("aid") Long aid) {

        return adminContestAnnouncementService.deleteAnnouncement(aid);
    }

    @PostMapping("/announcement")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> addAnnouncement(@RequestBody AnnouncementDTO announcementDto) {

        return adminContestAnnouncementService.addAnnouncement(announcementDto);
    }

    @PutMapping("/announcement")
    @RequiresRoles(value = {"root", "admin", "problem_admin"}, logical = Logical.OR)
    public CommonResult<Void> updateAnnouncement(@RequestBody AnnouncementDTO announcementDto) {

        return adminContestAnnouncementService.updateAnnouncement(announcementDto);
    }
}
